home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Browsers, Managers & Extensions / Mozilla Weave 0.2.7 / latest-weave.xpi / modules / util.js < prev    next >
Text File  |  2008-08-14  |  14KB  |  459 lines

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3.  *
  4.  * The contents of this file are subject to the Mozilla Public License Version
  5.  * 1.1 (the "License"); you may not use this file except in compliance with
  6.  * the License. You may obtain a copy of the License at
  7.  * http://www.mozilla.org/MPL/
  8.  *
  9.  * Software distributed under the License is distributed on an "AS IS" basis,
  10.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11.  * for the specific language governing rights and limitations under the
  12.  * License.
  13.  *
  14.  * The Original Code is Bookmarks Sync.
  15.  *
  16.  * The Initial Developer of the Original Code is Mozilla.
  17.  * Portions created by the Initial Developer are Copyright (C) 2007
  18.  * the Initial Developer. All Rights Reserved.
  19.  *
  20.  * Contributor(s):
  21.  *  Dan Mills <thunder@mozilla.com>
  22.  *
  23.  * Alternatively, the contents of this file may be used under the terms of
  24.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  25.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  26.  * in which case the provisions of the GPL or the LGPL are applicable instead
  27.  * of those above. If you wish to allow use of your version of this file only
  28.  * under the terms of either the GPL or the LGPL, and not to allow others to
  29.  * use your version of this file under the terms of the MPL, indicate your
  30.  * decision by deleting the provisions above and replace them with the notice
  31.  * and other provisions required by the GPL or the LGPL. If you do not delete
  32.  * the provisions above, a recipient may use your version of this file under
  33.  * the terms of any one of the MPL, the GPL or the LGPL.
  34.  *
  35.  * ***** END LICENSE BLOCK ***** */
  36.  
  37. const EXPORTED_SYMBOLS = ['Utils'];
  38.  
  39. const Cc = Components.classes;
  40. const Ci = Components.interfaces;
  41. const Cr = Components.results;
  42. const Cu = Components.utils;
  43.  
  44. Cu.import("resource://gre/modules/XPCOMUtils.jsm");
  45. Cu.import("resource://weave/constants.js");
  46. Cu.import("resource://weave/log4moz.js");
  47.  
  48. /*
  49.  * Utility functions
  50.  */
  51.  
  52. let Utils = {
  53.   // Generates a brand-new globally unique identifier (GUID).
  54.   makeGUID: function makeGUID() {
  55.     let uuidgen = Cc["@mozilla.org/uuid-generator;1"].
  56.                   getService(Ci.nsIUUIDGenerator);
  57.     return uuidgen.generateUUID().toString().replace(/[{}]/g, '');
  58.   },
  59.  
  60.   // Returns a nsILocalFile representing a file relative to the
  61.   // current user's profile directory.  If the argument is a string,
  62.   // it should be a string with unix-style slashes for directory names
  63.   // (these slashes are automatically converted to platform-specific
  64.   // path separators).
  65.   //
  66.   // Alternatively, if the argument is an object, it should contain
  67.   // the following attributes:
  68.   //
  69.   //   path: the path to the file, relative to the current user's
  70.   //   profile dir.
  71.   //
  72.   //   autoCreate: whether or not the file should be created if it
  73.   //   doesn't already exist.
  74.   getProfileFile: function getProfileFile(arg) {
  75.     if (typeof arg == "string")
  76.       arg = {path: arg};
  77.  
  78.     let pathParts = arg.path.split("/");
  79.     let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
  80.                  getService(Ci.nsIProperties);
  81.     let file = dirSvc.get("ProfD", Ci.nsIFile);
  82.     file.QueryInterface(Ci.nsILocalFile);
  83.     for (let i = 0; i < pathParts.length; i++)
  84.       file.append(pathParts[i]);
  85.     if (arg.autoCreate && !file.exists())
  86.       file.create(file.NORMAL_FILE_TYPE, PERMS_FILE);
  87.     return file;
  88.   },
  89.  
  90.   getLoginManager: function getLoginManager() {
  91.     return Cc["@mozilla.org/login-manager;1"].
  92.            getService(Ci.nsILoginManager);
  93.   },
  94.  
  95.   makeNewLoginInfo: function getNewLoginInfo() {
  96.     return new Components.Constructor(
  97.       "@mozilla.org/login-manager/loginInfo;1",
  98.       Ci.nsILoginInfo,
  99.       "init"
  100.     );
  101.   },
  102.  
  103.   findPassword: function findPassword(realm, username) {
  104.     // fixme: make a request and get the realm ?
  105.     let password;
  106.     let lm = Cc["@mozilla.org/login-manager;1"]
  107.              .getService(Ci.nsILoginManager);
  108.     let logins = lm.findLogins({}, 'chrome://sync', null, realm);
  109.  
  110.     for (let i = 0; i < logins.length; i++) {
  111.       if (logins[i].username == username) {
  112.         password = logins[i].password;
  113.         break;
  114.       }
  115.     }
  116.     return password;
  117.   },
  118.  
  119.   setPassword: function setPassword(realm, username, password) {
  120.     // cleanup any existing passwords
  121.     let lm = Cc["@mozilla.org/login-manager;1"]
  122.              .getService(Ci.nsILoginManager);
  123.     let logins = lm.findLogins({}, 'chrome://sync', null, realm);
  124.     for (let i = 0; i < logins.length; i++)
  125.       lm.removeLogin(logins[i]);
  126.  
  127.     if (!password)
  128.       return;
  129.  
  130.     // save the new one
  131.     let nsLoginInfo = new Components.Constructor(
  132.       "@mozilla.org/login-manager/loginInfo;1", Ci.nsILoginInfo, "init");
  133.     let login = new nsLoginInfo('chrome://sync', null, realm,
  134.                                 username, password, "", "");
  135.     lm.addLogin(login);
  136.   },
  137.  
  138.   // lazy load objects from a constructor on first access.  It will
  139.   // work with the global object ('this' in the global context).
  140.   lazy: function Weave_lazy(dest, prop, ctr) {
  141.     let getter = function() {
  142.       delete dest[prop];
  143.       dest[prop] = new ctr();
  144.       return dest[prop];
  145.     };
  146.     dest.__defineGetter__(prop, getter);
  147.   },
  148.  
  149.   deepEquals: function Weave_deepEquals(a, b) {
  150.     if (!a && !b)
  151.       return true;
  152.     if (!a || !b)
  153.       return false;
  154.  
  155.     // if neither is an object, just use ==
  156.     if (typeof(a) != "object" && typeof(b) != "object")
  157.       return a == b;
  158.  
  159.     // check if only one of them is an object
  160.     if (typeof(a) != "object" || typeof(b) != "object")
  161.       return false;
  162.  
  163.     if ("Array" == a.constructor.name && "Array" == b.constructor.name) {
  164.       if (a.length != b.length)
  165.         return false;
  166.  
  167.       for (let i = 0; i < a.length; i++) {
  168.         if (!Utils.deepEquals(a[i], b[i]))
  169.           return false;
  170.       }
  171.  
  172.     } else {
  173.       // check if only one of them is an array
  174.       if ("Array" == a.constructor.name || "Array" == b.constructor.name)
  175.         return false;
  176.  
  177.       for (let key in a) {
  178.         if (!Utils.deepEquals(a[key], b[key]))
  179.           return false;
  180.       }
  181.     }
  182.  
  183.     return true;
  184.   },
  185.  
  186.   deepCopy: function Weave_deepCopy(thing, noSort) {
  187.     if (typeof(thing) != "object" || thing == null)
  188.       return thing;
  189.     let ret;
  190.  
  191.     if ("Array" == thing.constructor.name) {
  192.       ret = [];
  193.       for (let i = 0; i < thing.length; i++)
  194.         ret.push(Utils.deepCopy(thing[i], noSort));
  195.  
  196.     } else {
  197.       ret = {};
  198.       let props = [p for (p in thing)];
  199.       if (!noSort)
  200.         props = props.sort();
  201.       props.forEach(function(k) ret[k] = Utils.deepCopy(thing[k], noSort));
  202.     }
  203.  
  204.     return ret;
  205.   },
  206.  
  207.   // Works on frames or exceptions, munges file:// URIs to shorten the paths
  208.   // FIXME: filename munging is sort of hackish, might be confusing if
  209.   // there are multiple extensions with similar filenames
  210.   formatFrame: function Utils_formatFrame(frame) {
  211.     let tmp = "<file:unknown>";
  212.     if (frame.filename)
  213.       tmp = frame.filename.replace(/^file:\/\/.*\/([^\/]+.js)$/, "module:$1");
  214.     else if (frame.fileName)
  215.       tmp = frame.fileName.replace(/^file:\/\/.*\/([^\/]+.js)$/, "module:$1");
  216.     if (frame.lineNumber)
  217.       tmp += ":" + frame.lineNumber;
  218.     if (frame.name)
  219.       tmp += " :: " + frame.name;
  220.     return tmp;
  221.   },
  222.  
  223.   exceptionStr: function Weave_exceptionStr(e) {
  224.     let message = e.message ? e.message : e;
  225.     let location = "";
  226.  
  227.     if (e.location) // Wrapped nsIException.
  228.       location = e.location;
  229.     else if (e.fileName && e.lineNumber) // Standard JS exception
  230.       location = Utils.formatFrame(e);
  231.  
  232.     if (location)
  233.       location = " (" + location + ")";
  234.     return message + location;
  235.  },
  236.  
  237.   stackTraceFromFrame: function Weave_stackTraceFromFrame(frame, formatter) {
  238.     if (!formatter)
  239.       formatter = function defaultFormatter(frame) { return frame; };
  240.  
  241.     let output = "";
  242.  
  243.     while (frame) {
  244.       output += formatter(frame) + "\n";
  245.       frame = frame.caller;
  246.     }
  247.  
  248.     return output;
  249.   },
  250.  
  251.   stackTrace: function Weave_stackTrace(e, formatter) {
  252.     if (e.asyncStack) // AsyncException
  253.       return e.asyncStack;
  254.     else if (e.location) // Wrapped nsIException
  255.       return this.stackTraceFromFrame(e.location, formatter);
  256.     else if (e.stack) // Standard JS exception
  257.       return e.stack;
  258.     else
  259.       return "No traceback available";
  260.   },
  261.  
  262.   checkStatus: function Weave_checkStatus(code, msg, ranges) {
  263.     if (!ranges)
  264.       ranges = [[200,300]];
  265.  
  266.     for (let i = 0; i < ranges.length; i++) {
  267.       var rng = ranges[i];
  268.       if (typeof(rng) == "object" && code >= rng[0] && code < rng[1])
  269.         return true;
  270.       else if (typeof(rng) == "number" && code == rng) {
  271.         return true;
  272.       }
  273.     }
  274.  
  275.     if (msg) {
  276.       let log = Log4Moz.Service.getLogger("Service.Util");
  277.       log.error(msg + " Error code: " + code);
  278.     }
  279.  
  280.     return false;
  281.   },
  282.  
  283.   ensureStatus: function Weave_ensureStatus(args) {
  284.     if (!Utils.checkStatus.apply(Utils, arguments))
  285.       throw 'checkStatus failed';
  286.   },
  287.  
  288.   sha1: function Weave_sha1(string) {
  289.     let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
  290.       createInstance(Ci.nsIScriptableUnicodeConverter);
  291.     converter.charset = "UTF-8";
  292.  
  293.     let hasher = Cc["@mozilla.org/security/hash;1"]
  294.       .createInstance(Ci.nsICryptoHash);
  295.     hasher.init(hasher.SHA1);
  296.  
  297.     let data = converter.convertToByteArray(string, {});
  298.     hasher.update(data, data.length);
  299.     let rawHash = hasher.finish(false);
  300.  
  301.     // return the two-digit hexadecimal code for a byte
  302.     function toHexString(charCode) {
  303.       return ("0" + charCode.toString(16)).slice(-2);
  304.     }
  305.  
  306.     let hash = [toHexString(rawHash.charCodeAt(i)) for (i in rawHash)].join("");
  307.     return hash;
  308.   },
  309.  
  310.   makeURI: function Weave_makeURI(URIString) {
  311.     if (URIString === null || URIString == "")
  312.       return null;
  313.     let ioservice = Cc["@mozilla.org/network/io-service;1"].
  314.       getService(Ci.nsIIOService);
  315.     return ioservice.newURI(URIString, null, null);
  316.   },
  317.  
  318.   xpath: function Weave_xpath(xmlDoc, xpathString) {
  319.     let root = xmlDoc.ownerDocument == null ?
  320.       xmlDoc.documentElement : xmlDoc.ownerDocument.documentElement;
  321.     let nsResolver = xmlDoc.createNSResolver(root);
  322.  
  323.     return xmlDoc.evaluate(xpathString, xmlDoc, nsResolver,
  324.                            Ci.nsIDOMXPathResult.ANY_TYPE, null);
  325.   },
  326.  
  327.   getTmp: function Weave_getTmp(name) {
  328.     let ds = Cc["@mozilla.org/file/directory_service;1"].
  329.       getService(Ci.nsIProperties);
  330.  
  331.     let tmp = ds.get("ProfD", Ci.nsIFile);
  332.     tmp.QueryInterface(Ci.nsILocalFile);
  333.  
  334.     tmp.append("weave");
  335.     tmp.append("tmp");
  336.     if (!tmp.exists())
  337.       tmp.create(tmp.DIRECTORY_TYPE, PERMS_DIRECTORY);
  338.  
  339.     if (name)
  340.       tmp.append(name);
  341.  
  342.     return tmp;
  343.   },
  344.  
  345.   // Returns a timer that is scheduled to call the given callback as
  346.   // soon as possible.
  347.   makeTimerForCall: function makeTimerForCall(cb) {
  348.     let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
  349.     timer.initWithCallback(new Utils.EventListener(cb),
  350.                            0, timer.TYPE_ONE_SHOT);
  351.     return timer;
  352.   },
  353.  
  354.   open: function open(pathOrFile, mode, perms) {
  355.     let stream, file;
  356.  
  357.     if (pathOrFile instanceof Ci.nsIFile) {
  358.       file = pathOrFile;
  359.     } else {
  360.       file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
  361.       dump("PATH IS" + pathOrFile + "\n");
  362.       file.initWithPath(pathOrFile);
  363.     }
  364.  
  365.     if (!perms)
  366.       perms = PERMS_FILE;
  367.  
  368.     switch(mode) {
  369.     case "<": {
  370.       if (!file.exists())
  371.         throw "Cannot open file for reading, file does not exist";
  372.       let fis = Cc["@mozilla.org/network/file-input-stream;1"].
  373.         createInstance(Ci.nsIFileInputStream);
  374.       fis.init(file, MODE_RDONLY, perms, 0);
  375.       stream = Cc["@mozilla.org/intl/converter-input-stream;1"].
  376.         createInstance(Ci.nsIConverterInputStream);
  377.       stream.init(fis, "UTF-8", 4096,
  378.                   Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
  379.     } break;
  380.  
  381.     case ">": {
  382.       let fos = Cc["@mozilla.org/network/file-output-stream;1"].
  383.         createInstance(Ci.nsIFileOutputStream);
  384.       fos.init(file, MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE, perms, 0);
  385.       stream = Cc["@mozilla.org/intl/converter-output-stream;1"]
  386.         .createInstance(Ci.nsIConverterOutputStream);
  387.       stream.init(fos, "UTF-8", 4096, 0x0000);
  388.     } break;
  389.  
  390.     case ">>": {
  391.       let fos = Cc["@mozilla.org/network/file-output-stream;1"].
  392.         createInstance(Ci.nsIFileOutputStream);
  393.       fos.init(file, MODE_WRONLY | MODE_CREATE | MODE_APPEND, perms, 0);
  394.       stream = Cc["@mozilla.org/intl/converter-output-stream;1"]
  395.         .createInstance(Ci.nsIConverterOutputStream);
  396.       stream.init(fos, "UTF-8", 4096, 0x0000);
  397.     } break;
  398.  
  399.     default:
  400.       throw "Illegal mode to open(): " + mode;
  401.     }
  402.  
  403.     return [stream, file];
  404.   },
  405.  
  406.   // assumes an nsIConverterInputStream
  407.   readStream: function Weave_readStream(is) {
  408.     let ret = "", str = {};
  409.     while (is.readString(4096, str) != 0) {
  410.       ret += str.value;
  411.     }
  412.     return ret;
  413.   },
  414.  
  415.   bind2: function Async_bind2(object, method) {
  416.     return function innerBind() { return method.apply(object, arguments); };
  417.   },
  418.  
  419.   __prefs: null,
  420.   get prefs() {
  421.     if (!this.__prefs) {
  422.       this.__prefs = Cc["@mozilla.org/preferences-service;1"]
  423.         .getService(Ci.nsIPrefService);
  424.       this.__prefs = this.__prefs.getBranch(PREFS_BRANCH);
  425.       this.__prefs.QueryInterface(Ci.nsIPrefBranch2);
  426.     }
  427.     return this.__prefs;
  428.   },
  429.  
  430.   /*
  431.    * Event listener object
  432.    * Used to handle XMLHttpRequest and nsITimer callbacks
  433.    */
  434.  
  435.   EventListener: function Weave_EventListener(handler, eventName) {
  436.     this._handler = handler;
  437.     this._eventName = eventName;
  438.     this._log = Log4Moz.Service.getLogger("Async.EventHandler");
  439.     this._log.level =
  440.       Log4Moz.Level[Utils.prefs.getCharPref("log.logger.async")];
  441.   }
  442. };
  443.  
  444. Utils.EventListener.prototype = {
  445.   QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback, Ci.nsISupports]),
  446.  
  447.   // DOM event listener
  448.   handleEvent: function EL_handleEvent(event) {
  449.     this._log.trace("Handling event " + this._eventName);
  450.     this._handler(event);
  451.   },
  452.  
  453.   // nsITimerCallback
  454.   notify: function EL_notify(timer) {
  455.     //this._log.trace("Timer fired");
  456.     this._handler(timer);
  457.   }
  458. }
  459.